package com.aabte.commons.gson;

import com.aabte.commons.json.JSONException;
import com.aabte.commons.json.JSONIOException;
import com.aabte.commons.json.JSONSerializationAdapter;
import com.aabte.commons.json.JSONSyntaxException;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.LongSerializationPolicy;
import java.io.Reader;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import org.apache.commons.lang3.reflect.TypeUtils;

/**
 * @author Daniel
 * @version 1.0
 * @date 2020/4/5
 */
public class GsonSerializationAdapter implements JSONSerializationAdapter {

  private static Gson GSON;

  static {
    GSON = new GsonBuilder()
        .setLongSerializationPolicy(LongSerializationPolicy.STRING)
        .create();
  }

  public static Gson getGSON() {
    return GSON;
  }

  public static void setGSON(Gson GSON) {
    GsonSerializationAdapter.GSON = GSON;
  }

  @Override
  public String toJson(Object src) throws JSONException {
    return GSON.toJson(src);
  }

  @Override
  public String toJson(Object src, Type typeOfSrc) throws JSONException {
    return GSON.toJson(src, typeOfSrc);
  }

  @Override
  public void toJson(Object src, Appendable writer) throws JSONIOException {
    GSON.toJson(src, writer);
  }

  @Override
  public <T> T fromJson(String json, Type typeOfT) throws JSONSyntaxException {
    return GSON.fromJson(json, typeOfT);
  }

  @Override
  public <T> T fromJson(String json, Class<T> classOfT) throws JSONSyntaxException {
    return fromJson(json, classOfT, (Type[]) null);
  }

  @Override
  public <T> T fromJson(String json, Class<T> classOfT, Type... typeArguments)
      throws JSONSyntaxException {
    if (null == typeArguments || typeArguments.length == 0) {
      return GSON.fromJson(json, classOfT);
    } else {
      ParameterizedType type = TypeUtils.parameterize(classOfT, typeArguments);
      return GSON.fromJson(json, type);
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> T fromJsonArray(String json, Type typeArguments) throws JSONSyntaxException {
    return (T) GSON.fromJson(json, typeArguments);
  }

  @Override
  public <T> T fromJson(Reader json, Class<T> classOfT) throws JSONSyntaxException {
    return GSON.fromJson(json, classOfT);
  }

  @Override
  public <T> T fromJson(Reader json, Type typeOfT) throws JSONSyntaxException {
    return GSON.fromJson(json, typeOfT);
  }
}
